
/*
 * Copyright (C) 2008-2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id: SidekarIndex.java 288 2010-01-11 19:45:47Z archie.cobbs $
 */

package org.dellroad.sidekar.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Defines an index on one or more fields of a Sidekar entity.
 *
 * <p>
 * {@link SidekarIndex} annotations constitute the {@link SidekarEntity#indexes indexes} field of the
 * {@link SidekarEntity} annotation.
 *
 * <p>
 * Only field types that subclass {@link org.dellroad.sidekar.SimpleField} are indexable (basically,
 * any field type except collection types).
 *
 * <p>
 * Example:
 *  <blockquote>
 *  <pre>
 *  &#64;SidekarEntity(indexes = { &#64;SidekarIndex(name = "byName", fields = { "name" } })
 *  public abstract class Employee {
 *
 *      &#64;SidekarField
 *      public abstract String getName();
 *      public abstract void setName(String name);
 *
 *      // rest of class...
 *  }
 *  </pre>
 *  </blockquote>
 *
 * <p>
 * To find all {@code Employee} instances with name {@code "fred"}:
 *  <blockquote>
 *  <pre>
 *  Iterator&lt;Employee&gt; i = db.getEntity(Employee.class).getIndex("byName").get("fred");
 *  </pre>
 *  </blockquote>
 *
 * <p>
 * To get all {@code Employee} instances sorted by name:
 *  <blockquote>
 *  <pre>
 *  Iterator&lt;Employee&gt; i = db.getEntity(Employee.class).getIndex("byName").get();
 *  </pre>
 *  </blockquote>
 *
 * @see SidekarEntity
 * @see org.dellroad.sidekar.FieldType Supported field types (and how they sort)
 */
@Documented
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SidekarIndex {

    /**
     * Specifies the name of this index.
     *
     * <p>
     * Only field types that subclass {@link org.dellroad.sidekar.SimpleField} are indexable (basically,
     * any field type except collection types).
     *
     * <p>
     * Index names are scoped to the entity being indexed and must be unique for
     * that entity. Names must be non-empty and contain no periods, slashes, or dollar signs.
     */
    String name();

    /**
     * Specifies whether the index should have a uniqueness constraint.
     *
     * <p>
     * If this is true, any attempt to create a second instance of an item with the
     * same values for all of the indexed fields as an existing instance will cause
     * an exception to be thrown.
     *
     * <p>
     * Note that items are indexed as soon as they are created, so for example two
     * newly created items that have not been modified from their default states
     * will index the same way.
     */
    boolean unique() default false;

    /**
     * Specifies the names of the indexed fields in the target entity.
     * There must be at least one indexed field.
     */
    String[] fields();
}

